<?php

/**
 * @desc 融宝支付
 * @author 刘冰冰
 */

namespace Service\Pay\Reapal;

defined('THINK_PATH') or exit();

use Service\Pay;

class Reapal extends Pay {

    private $private_key;//私钥
    private $public_key;//公钥

    function __construct($options=array()) {
       if(empty($options)) {
            $pay_config = C('PAY_CONFIG');
            $options = isset($pay_config['Reapal'])?$pay_config['Reapal']:array();
        }
        $this->options = $options;
        $this->public_key=file_get_contents ($this->options['public_key_path']);
        $this->private_key=file_get_contents ($this->options['private_key_path']);

    }

    /**
     * @desc 绑卡
     * @author 刘冰冰
     * @param array $data
     */
    public function bind($data){
        return $data;
    }

    /**
     * @desc 访问储蓄卡签约服务 即用户第一次使用要调用 返回绑定id（可以称作帮卡接口）
     * @author 刘冰冰
     * @param array $data
     */
    public function prePay($data){
        $rts=array();
        if(empty($data['card_name'])){
            $rts['rt']=-1;
            $rts['msg']='用户姓名不能为空！';
            return $rts;
        }
        if(empty($data['user_id'])){
            $rts['rt']=-2;
            $rts['msg']='用户id不能为空！';
            return $rts;
        }
        if(empty($data['bank_card_number'])){
            $rts['rt']=-3;
            $rts['msg']='用户银行卡号不能为空！';
            return $rts;
        }
        if(empty($data['id_card'])){
            $rts['rt']=-4;
            $rts['msg']='用户身份证号不能为空！';
            return $rts;
        }
        if(empty($data['order_sn'])){
            $rts['rt']=-5;
            $rts['msg']='订单编号不能为空！';
            return $rts;
        }
        if(empty($data['mobile'])){
            $rts['rt']=-6;
            $rts['msg']='用户手机号不能为空！';
            return $rts;
        }
        if(empty($data['amount'])){
            $rts['rt']=-7;
            $rts['msg']='用户支付金额不能为空！';
            return $rts;
        }
        if(empty($data['ip'])){
            $rts['rt']=-8;
            $rts['msg']='用户IP不能为空！';
            return $rts;
        }
        $parms = array();
        $parms["cert_type"]='01';
        $parms["owner"]=$data['card_name'];
        $parms["merchant_id"]=$this->options['merchant_id']; //商户订单编号
        $parms["card_no"]=$data['bank_card_number'];//卡号
        $parms["cert_no"]=$data['id_card'];//身份证号
        $parms["member_id"]=$data['user_id'];//用户id
        $parms["phone"]=$data['mobile'];//预留手机号
        $parms["order_no"]= $data['order_sn'];//商户流水号,8-20 位字母和数字，每次请求都不可重复(当天和历史均不可重复)
        $parms["transtime"] = date('Y-m-d H:i:s');//交易时间
        $parms["currency"] = '156';//交易币种
        $parms["total_fee"] = $data['amount']*100;//分为单位
        $parms["title"] = '稻子金服';  //商品名
        $parms["body"] = '稻子金服';  //商品描述
        $parms["terminal_type"]=$this->options['terminal_type']; //终端类型 mobile、web、wap
        $parms["member_ip"]=$data['ip'];
        $parms["seller_email"]= $this->options['seller_email'];//商户邮箱
        $parms["notify_url"]=$this->options['notify_url'].'userid/'.$data['user_id'];//异步通知地址
        $parms["token_id"]=uniqid();//融宝用于交易时风控进行安全的判断，100位以内，建议用UUID的生成方法
        $parms["terminal_info"]=uniqid();//格式为IMEI_MAC/序列号_SIM
        $parms["version"]= $this->options['version'];
        $url = $this->options['api_url'].'/fast/same/debit/portal';
        return $this->_send($parms, $url);
    }

    /**
     * @desc 查询绑卡信息
     * @author 刘冰冰
     * @param array $data
     */
    public function queryBindStatus($data){
        $rts=array();
        if(empty($data['user_id'])){
            $rts['rt']=-1;
            $rts['msg']='用户id不能为空！';
            return $rts;
        }
       //参数数组
        $params = array(
             'merchant_id' => $this->options['merchant_id'],
             'member_id' => $data['user_id'],
            	 'bank_card_type' => '0',//0储蓄卡 1是信用卡
            	 'version' => $this->options['version']
        );
        $url = $this->options['api_url'].'/fast/bindcard/list';
        return $this->_send($params, $url);
    }

    /**
     * @desc 解绑银行卡
     * @author 刘冰冰
     * @param array $data
     */
    public function unBind($data){
        $rts=array();
        if (!isset($data['user_id'])) {
            $rts['rt']=-1;
            $rts['msg']='用户id不能为空！';
            return $rts;
        }
        $rts=$this->__queryBindStatus($data);
        if(empty($rts['return_data']['bind_card_list'])){
            $rts['rt']=-2;
            $rts['msg']='银行卡的绑定关系不存在！';
            return $rts;
        }
        $data['bind_id']=$rts['return_data']['bind_card_list'][0]['bind_id'];
        if(empty($data['bind_id'])){
            $rts['rt']=-3;
            $rts['msg']='绑定号缺失！';
            return $rts;
        }
        $params = array(
             'merchant_id' => $this->options['merchant_id'],
             'member_id' => $data['user_id'],
        	 'bind_id' => $data['bind_id'],
             'version' => $this->options['version']
           );
        $url = $this->options['api_url'].'/fast/cancle/bindcard';
        return $this->_send($params, $url);
    }

    /**
     * @desc 帮卡签约接口（用户非首次使用调用） 即：用户使用已绑定的银行卡支付时调用，发送短信(预支付)
     * @author 刘冰冰
     * @param array $data
     */
    public function prePay1($data){
        $rts=array();
        if (!isset($data['order_sn'])) {
            $rts['rt']=-1;
            $rts['msg']='订单编号不能为空！';
            return $rts;
        }
        if (!isset($data['bind_id'])) {
            $rts['rt']=-2;
            $rts['msg']='绑定号不能为空！';
            return $rts;
        }
        if (!isset($data['user_id'])) {
            $rts['rt']=-3;
            $rts['msg']='用户id不能为空！';
            return $rts;
        }
        $amount=floatval($data['amount'])*100;
        if($amount<=0){
            $rts['rt']=-4;
            $rts['msg']='支付金额不正确！';
            return $rts;
        }
        if (!isset($data['ip'])) {
            $rts['rt']=-5;
            $rts['msg']='IP不能为空！';
            return $rts;
        }
        //参数数组
        $params = array(
             'merchant_id' => $this->options['merchant_id'],
             'bind_id' => $data['bind_id'],
             'order_no' =>$data['order_sn'],
             'transtime' => date('Y-m-d H:i:s'),
             'currency' => '156',
             'title' => '稻子金服',
             'body' => '稻子金服',
             'member_id' => $data['user_id'],
             'terminal_type'=>$this->options['terminal_type'],
             'terminal_info' => uniqid(),
             'member_ip' => $data['ip'],
             'seller_email' => $this->options['seller_email'],
        	 'total_fee' => $amount
        );

        //访问绑卡签约服务
        $url = $this->options['api_url'].'/fast/bindcard/portal';
        return $this->_send($params, $url);
    }

    /**
     * @desc 确认支付
     * @author 陈聪
     * @param array $data
     */
    public function pay($data){
        $rts=array();
        if (!isset($data['order_no'])) {
            $rts['rt']=-1;
            $rts['msg']='订单号不能为空！';
            return $rts;
        }
        if (!isset($data['sms_code'])) {
            $rts['rt']=-2;
            $rts['msg']='短信验证码不能为空！';
            return $rts;
        }
        $params = array(
            'merchant_id' => $this->options['merchant_id'],
            'order_no' => $data['order_no'],
            'check_code' => $data['sms_code']
        );
        $url = $this->options['api_url'].'/fast/pay';
        return $this->_send($params, $url);
    }

    /**
     * @desc 付款订单状态查询
     * @author 刘冰冰
     */
    public function queryPayStatus($data){
        $rts=array();
        if (!isset($data['order_sn'])) {
            $rts['rt']=-1;
            $rts['msg']='订单号不能为空！';
            return $rts;
        }
        $params = array(
             'merchant_id' => $this->options['merchant_id'],
             'order_no' => $data['order_sn'],
             'version' => $this->options['version']
           );
        $url = $this->options['api_url'].'/fast/search';
        return $this->_send($params, $url,0);
    }

    /**
     * @desc 银行卡信息查询接口
     * @author 刘冰冰
     * @param unknown $data
     * @return string
     */
    public function queryBank($data){
        $rts=array();
        if(empty($data['bank_card_number'])){
            $rts['rt']=-1;
            $rts['msg']='银行卡号不能为空！';
            return $rts;
        }
        $params = array(
            'merchant_id' => $this->options['merchant_id'],
            'card_no' => $data['bank_card_number'],
            'version' =>$this->options['version']
        );

        $url = $this->options['api_url'].'/fast/bankcard/list';
        return $this->_send($params, $url);
    }

    /**
     * @desc 卡密鉴权接口（目前只针对招商银行借记卡）
     * @author 刘冰冰
     */
    public function certificate($data){
        $rts=array();
        if(empty($data['bind_id'])){
            $rts['rt']=-1;
            $rts['msg']='银行绑定号不能为空！';
            return $rts;
        }
        if(empty($data['user_id'])){
            $rts['rt']=-2;
            $rts['msg']='用户id不能为空！';
            return $rts;
        }
        if(empty($data['order_sn'])){
            $rts['rt']=-3;
            $rts['msg']='交易订单号不能为空！';
            return $rts;
        }
        $params = array(
            'merchant_id' => $this->options['merchant_id'],
            'member_id' => $data['user_id'],
            'bind_id' => $data['bind_id'],
            'order_no' => $data['order_sn'],
            "return_url" => $this->options['return_url'],
            "notify_url" => $this->options['notify_url'],
            "terminal_type" => $this->options['terminal_type'],
            'version' => $this->options['version']
        );
        $url = $this->options['api_url'].'/fast/certificate';
        return $this->_send($params, $url);
    }

    /**
     * @desc 持卡人更改银行预留手机号
     * @author 刘冰冰
     * @param unknown $data
     */
    public function changePhone($data){
        $rts=array();
        if(empty($data['card_name'])){
            $rts['rt']=-1;
            $rts['msg']='用户姓名不能为空！';
            return $rts;
        }
        if(empty($data['user_id'])){
            $rts['rt']=-2;
            $rts['msg']='用户id不能为空！';
            return $rts;
        }
        if(empty($data['bank_card_number'])){
            $rts['rt']=-3;
            $rts['msg']='用户银行卡号不能为空！';
            return $rts;
        }
        if(empty($data['id_card'])){
            $rts['rt']=-4;
            $rts['msg']='用户身份证号不能为空！';
            return $rts;
        }
        if(empty($data['mobile'])){
            $rts['rt']=-5;
            $rts['msg']='用户手机号不能为空！';
            return $rts;
        }
        $params=array(
            "merchant_id"=> $this->options['merchant_id'],
            "bind_id"=>$data['bind_id'],
            "card_no"=> $data['bank_card_number'],
            "cert_no"=> $data['id_card'],
            "cert_type"=> "01",
            "member_id"=> $data['user_id'],
            "owner"=> $data['card_name'],
            "phone"=> $data['mobile'],
            "version"=> $this->options['version']
         );
        $url = $this->options['api_url'].'/fast/changePhone';
        return $this->_send($params, $url);
    }

    /**
     * @desc 发送请求
     * @author 刘冰冰
     * @param 请求参数 $paramArr
     * @param 请求地址 $url
     * @return string
     */
    private function _send($paramArr, $url , $is_logs=1){
        //生成签名
        $sign = $this->_createSign($paramArr,$this->options['api_key']);
        $paramArr['sign'] = $sign;
        //生成AESkey
        $generateAESKey = $this->_generateAESKey();
        $request = array();
        $request['merchant_id'] = $this->options['merchant_id'];
        //加密key
        $request['encryptkey'] = $this->_RSAEncryptkey($generateAESKey);
        //加密数据
        $request['data'] = $this->_AESencrypt($generateAESKey,$paramArr);
        $result=$this->curl_post($url, http_build_query($request));
        if($is_logs==1){
            /*记录未解密数据*/
            third_party_api_log($url,$paramArr,$result,$this->options['type']);
        }
        $response = json_decode($result,true);
        $encryptkey = $this->_RSADecryptkey($response['encryptkey']);
        $rt=$this->_AESdecrypt($encryptkey,$response['data']);
        $rt_arr = json_decode($rt,true);
        $rts = array();
        if(empty($rt_arr)){
            $rts['rt']=-1;
            $rts['msg']='返回参数为空!';
        }else if($rt_arr['result_code']=='0000'){
            $rts['rt']=1;
            $rts['msg']='交易成功!';
            $rts['return_data']=$rt_arr;//接口返回的数据
        }else{
            $rts['rt']=-2;
            $rts['msg']=$rt_arr['result_msg']?$rt_arr['result_msg']:$rt_arr['status'];
            $rts['return_data']=$rt_arr;//接口返回的数据
        }
        if($is_logs==1){
            /*记录解密后数据*/
            third_party_api_log($url,$paramArr,$rt,$this->options['type']);
        }
        return $rts;
    }

    /**
     * @desc 把请求参数组装报文
     * @return string
     */
    private function _getRequestParamString($params) {
        $params_str = '';
        foreach ( $params as $key => $value ) {
            $params_str .= ($key . '=' . (!isset ( $value ) ? '' : urlencode( $value )) . '&');
        }
        return substr ( $params_str, 0, strlen ( $params_str ) - 1 );
    }

    /**
     * @desc 签名函数
     * @author 刘冰冰
     * @param unknown $paramArr
     * @param unknown $apiKey
     * @return unknown
     */
    private function _createSign ($paramArr,$apiKey) {
        $sign = '';
        ksort($paramArr);
        foreach ($paramArr as $key => $val) {
            if ($key != '' && $val != '') {
                $sign .= $key.'='.$val.'&';
            }
        }
        $sign = substr ( $sign,0,(strlen ( $sign )-1));
        $sign = md5($sign.$apiKey);
        return $sign;
    }

    /**
     * @desc 生成一个随机的字符串作为AES密钥
     * @param number $length
     * @return string
     */
    private function _generateAESKey($length=16){
        $baseString = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        $AESKey = '';
        $_len = strlen($baseString);
        for($i=1;$i<=$length;$i++){
            $AESKey .= $baseString[rand(0, $_len-1)];
        }
        return $AESKey;
    }

    /**
     * @desc 通过RSA，使用融宝公钥，加密本次请求的AESKey
     * @return string
     */
    private function _RSAEncryptkey($encryptKey){
        $pu_key = openssl_pkey_get_public($this->public_key);//这个函数可用来判断公钥是否是可用的
        openssl_public_encrypt($encryptKey,$encrypted,$pu_key);//公钥加密
        return base64_encode($encrypted);
    }

    /**
     * @desc 通过RSA，使用融宝公钥，解密本次请求的AESKey
     * @return string
     */
    private function _RSADecryptkey($encryptKey){
        $pi_key =  openssl_pkey_get_private($this->private_key);//这个函数可用来判断私钥是否是可用的，可用返回资源id Resource id
        openssl_private_decrypt(base64_decode($encryptKey),$decrypted,$pi_key);//私钥解密
        return $decrypted;
    }

    /**
     * @desc 通过AES加密请求数据
     * @author 刘冰冰
     * @param unknown $param
     * @return unknown
     */
    private function _AESencrypt($encryptKey,$param) {
        $param=json_encode($param);
        $size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
        $param = $this->_pkcs5_pad($param, $size);
        $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
        $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
        mcrypt_generic_init($td, $encryptKey, $iv);
        $data = mcrypt_generic($td, $param);
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);
        $data = base64_encode($data);
        return $data;
    }

    /**
     * @desc  填充字符串
     * @author 刘冰冰
     * @param unknown $text
     * @param unknown $blocksize
     * @return string
     */
    private function _pkcs5_pad ($text, $blocksize) {
        $pad = $blocksize - (strlen($text) % $blocksize);
        return $text . str_repeat(chr($pad), $pad);
    }

    /**
     * @desc 通过AES解密请求数据
     * @author 刘冰冰
     * @param unknown $param
     */
    private function _AESdecrypt($encryptKey,$param){
        $decrypted= mcrypt_decrypt(MCRYPT_RIJNDAEL_128,$encryptKey,base64_decode($param),MCRYPT_MODE_ECB);
        $dec_s = strlen($decrypted);
        $padding = ord($decrypted[$dec_s-1]);
        $decrypted = substr($decrypted, 0, -$padding);
        return $decrypted;
    }
}
